package com.briup.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.briup.common.constant.SystemConstant;
import com.briup.common.utils.BeanUtil;
import com.briup.server.domain.bean.Labs;
import com.briup.server.domain.bean.User;
import com.briup.server.domain.dto.ConditionQueryDTO;
import com.briup.server.domain.vo.LabsDetailVO;
import com.briup.server.domain.vo.RoleVO;
import com.briup.server.mapper.LabsMapper;
import com.briup.server.security.SecurityContext;
import com.briup.server.service.LabsAdminRService;
import com.briup.server.service.LabsService;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;

@Service
public class LabsServiceImpl extends ServiceImpl<LabsMapper, Labs>
        implements LabsService {

    /*
     * 实验室管理员关系服务的创建，依赖于LabsService，
     * 而在当前LabsService中，也依赖于LabsAdminRService，
     * 为了避免循环依赖，这里使用@Lazy注解，
     * 确保在LabsAdminRService实例被创建后，在注入到LabsServiceImpl中；
     *
     * 并且在本类中，没有使用构造器的方式注入LabsAdminRService，
     * 而是使用@Resource注解的方式注入，
     * 就是为了保证先使用无参构造器创建LabsService实例，
     * 确保在LabsAdminRService实例被创建时，LabsService实例是创建成功的；
     *
     */
    @Lazy
    @Resource
    private LabsAdminRService labsAdminRService;

    @Override
    public Page<LabsDetailVO> pageQuery(ConditionQueryDTO queryDTO) {
        // 创建分页对象
        Page<Labs> page = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        // 构建查询构造器
        LambdaQueryWrapper<Labs> wrapper = Wrappers.<Labs>lambdaQuery()
                .like(StringUtils.hasText(queryDTO.getName()),
                        Labs::getLabsName, queryDTO.getName());
        // 分页查询，会自动将查询的结果封装到page分页对象中
        page(page, wrapper);
        // 转换为VO
        Page<LabsDetailVO> labsDetailVOPage = BeanUtil.convertPage(page, LabsDetailVO.class);
        // 给vo设置管理员列表
        labsDetailVOPage.getRecords().forEach(labsDetailVO -> {
            List<User> admins = labsAdminRService.queryAdmins(labsDetailVO.getId());
            labsDetailVO.setAdmins(admins.stream().map(User::getRealname).toList());
            // 为了防止存在真实姓名相同的情况，所以这里还需要根据id来唯一确定实验室管理员
            labsDetailVO.setAdminIds(admins.stream().map(User::getId).toList());
        });
        // 获取当前用户的角色列表，如果当前用户是超级管理员，那么返回所有的数据，
        // 如果是实验室管理员，那么返回当前实验室管理员管理的实验室列表；
        // 如果不是超级管理员，也不是实验室管理员，那么返回空列表
        List<RoleVO> roles = SecurityContext.currentUser().getRoles();
        boolean isSuperAdmin = roles.stream().anyMatch(
                roleVO -> roleVO.getName().equalsIgnoreCase(SystemConstant.ADMIN_ROLE_NAME));
        boolean isLabAdmin = roles.stream().anyMatch(
                roleVO -> roleVO.getName().equalsIgnoreCase(SystemConstant.LAB_ADMIN_ROLE_NAME));
        if (!isSuperAdmin && isLabAdmin) {
            // 过滤出当前实验室管理员管理的实验室列表，
            // 这里需要根据实验室管理员的id来判断是否是当前实验室管理员管理的实验室
            labsDetailVOPage.getRecords().removeIf(labsDetailVO ->
                    !labsDetailVO.getAdminIds().contains(SecurityContext.currentUser().getId()));
        } else if (!isSuperAdmin) {
            // 不是实验室管理员，返回空列表
            labsDetailVOPage.getRecords().clear();
        }
        // 手动设置总记录数，因为分页查询不会自动统计总记录数
        labsDetailVOPage.setTotal(labsDetailVOPage.getRecords().size());
        // 返回分页结果
        return labsDetailVOPage;
    }
}




